using System;
using Grammars.Core;

namespace Grammars.Examples
{
    public static class ABCGrammar
    {
        public class ABCNode : Node
        {
            public int Count { get; set; }
            public bool Ok { get; set; }
        }

        public static void Run()
        {
            var G = new Grammar<ABCNode>();

            // Rules
            var S = G.StartSymbol;
            var A = G.Rule();
            var B = G.Rule();
            var C = G.Rule();

            // Tokens
            var a = G.Token('a');
            var b = G.Token('b');
            var c = G.Token('c');

            // Productions
            S %= (A + B + C).With(x => x.Ok = A.Node.Count == B.Node.Count && A.Node.Count == C.Node.Count);
            A %= (A + a).With(x => x.Count = A.Node.Count + 1) | a.With(x => x.Count = 1);
            B %= (B + b).With(x => x.Count = B.Node.Count + 1) | b.With(x => x.Count = 1);
            C %= (C + c).With(x => x.Count = C.Node.Count + 1) | c.With(x => x.Count = 1);

            var parser = Parsers.BuildLr(G);

            while (true)
            {
                // Enter the evaluation loop
                while (true)
                {
                    // Read the expression
                    Console.WriteLine("Enter an string (empty to exit):");
                    string exp = Console.ReadLine();

                    if (string.IsNullOrEmpty(exp))
                        break;

                    // Parse (and evaluate) the expression
                    var node = parser.ParseString(exp);

                    // Print the result
                    Console.WriteLine(node.Ok);
                }
            }
        }
    }
}